/*
 * FloorProxy.h
 *
 *  Created on: 22/04/2012
 *      Author: alex
 */

#ifndef FLOORPROXY_H_
#define FLOORPROXY_H_

#include <map>
#include <vector>
#include "PassengerQueue.h"
#include "ElevatorPassenger.h"
#include "../IPC/SharedMemory.h"
#include "../IPC/LockFile.h"
#include "../common/Object.h"

/**
 * Se encarga de encapsular el manejo de los pisos, instanciando
 * los procesos y mecanismos de comunicacion necesarios
 */
class FloorProxy: public Object
{
private:
	//TYPEDEFS
	typedef std::map<FloorIdentifier,PassengerQueue *> QueueVector;

	/**
	 * Vector con los pids de todos los procesos hijos
	 */
    std::vector<pid_t> m_PidVector;

    /**
     * Vector con las PassengerQueue de cada piso.
     * Los PassengerQueue se utilizaran para comunicar los
     * pasajeros que hay esperando en cada piso.
     */
    QueueVector m_PassengerQueue;

    /**
     * Cantidad de pisos instanciados.
     */
    int m_FloorAmmount;

    /**
     * Path de base, a partir del cual se crearan los pisos
     * y mecanismos de control.
     * Los pisos tendran un nombre de la forma:
     * "m_BaseFileName+numPiso"
     */
    std::string m_BaseFileName;

    std::string m_keyGeneratorPath;

    /**
     *
     */
    bool m_IsRunning;

    /**
     *
     */
    bool m_didStartProcesses;

public:

    /**
     * Construct
     * @param floorAmmount Cantidad de pisos a utilizar
     * @param baseFileName Nombre que se usara como base para crear los
     * 		  mecanismos de IPC (se debe tener permisos sobre ese dir)
     */
    FloorProxy(int floorAmmount,std::string keyGeneratorPath, std::string baseFileName);

    /**
     * Destruct
     */
    virtual ~FloorProxy();

    /**
     * Inicia los pisos, instanciando todos los procesos y
     * mecanismos de control necesarios
     */
    void start(bool startProcesses= true);

    /**
     * Detiene a los pisos, para todos los procesos hijos y
     * destruye las estructuras de control utilizadas
     */
    void stop();

    /**
     *
     */
    void stopGeneratingPassengers();

    /**
     * Obtiene la cantidad de pisos seteada
     * @returns int cantidad de pisos
     */
    int getFloorAmmount();

    /**
     * Retorna si hay pasajeros en espera para un piso determinado
     * @param floorId id del piso
     * @returns bool true si hay pasajeros, false en caso contrario.
     */
    bool hasPassengers(FloorIdentifier floorId);

    /**
     * Indica que el pasajero que se pidio anteriormente mediante
     * un peek debe ser eliminado.
     */
    void deletePeekedPassenger(FloorIdentifier floorId);

    /**
     * Obtiene un pasajero de un piso, sin removerlo del piso
     * El obj devuelto debe ser liberado por el invocador.
     * @param floorId id del piso por el cual se pregunta.
     * @returns ElevatorPassenger * pasajero del ascensor.
     */
    ElevatorPassenger * peekPassenger(FloorIdentifier floorId);

    /**
     * Obtiene un pasajero de un piso, removiendolo
     * del piso.
     * El obj devuelto debe ser liberado por el invocador.
     * @param floorId id del piso por el cual se pregunta.
     * @returns ElevatorPassenger * pasajero del ascensor.
     */
    ElevatorPassenger * getPassenger(FloorIdentifier floorId);

    /**
     * Obtiene una lista con los pisos en los cuales hay
     * pasajeros encolados
   	 * @returns FloorList lista de los pisos en los cuales habia
   	 * 			gente esperando cuando se llamo el metodo.
     */
    FloorIdentifierList getWaitingFloors();

    /**
     *
     *
     */
    bool isRunning();
};

#endif // FLOORPROXY_H_
